
#include "Stdafx.h"
#include "IoPacketPool.h"
#include "ssession.h"
#include "NetPacket.h"

//////////////////////////////////////////////////////////////////////////
//	IoPacketPool
//////////////////////////////////////////////////////////////////////////
IoPacketPool::IoPacketPool()
{
	Create();
}

IoPacketPool::~IoPacketPool()
{
	Destroy();
}
 
void 
IoPacketPool::Create()
{
	//IoPacketPool::PoolList IoPacketPool::g_List[E_MAX_PACKET_POOL];
	g_allocSize = (unsigned long)-1;
	g_deallocPos = E_MAX_PACKET_POOL-1;
	for (int i = 0 ; i < E_MAX_PACKET_POOL; i++) 
	{
		PoolList *pPoolList = &g_List[i];
		pPoolList->m_pBuffer = NULL;
	}
}

void 
IoPacketPool::Destroy()
{
	FreeAll();
}

void IoPacketPool::FreeAll()
{
	for (int i = 0 ; i < E_MAX_PACKET_POOL; ++i) 
	{
		PoolList *pPoolList = &g_List[i];
		pPoolList->m_lock.Lock();
		IocpPacket* pBuffer=pPoolList->m_pBuffer;
		while(NULL!=pBuffer)
		{
			pPoolList->m_pBuffer = pBuffer->m_pNext;
			PacketAlloc::PopCheckList(pBuffer);
			delete pBuffer;
			pBuffer=pPoolList->m_pBuffer;
		}
		pPoolList->m_lock.Unlock();
	}

	PacketAlloc::CheckList();

	CmTRACE( L"IocpPacket::FreeAll allAlloced size is  %d \n", g_allocSize );
}

void IoPacketPool::Free(IocpPacket *pIocpPacket)
{
	PoolList *pPoolList=&g_List[InterlockedDecrement(&g_deallocPos) & (E_MAX_PACKET_POOL-1)];

	pPoolList->m_lock.Lock();

	pIocpPacket->m_pNext = pPoolList->m_pBuffer; 
	pPoolList->m_pBuffer = pIocpPacket;

	pIocpPacket->SetUse(false);

	pPoolList->m_lock.Unlock();
}

IocpPacket* IoPacketPool::AllocBuffer()
{
	PoolList *pPoolList=&g_List[InterlockedIncrement(&g_allocSize) & (E_MAX_PACKET_POOL-1)];
	pPoolList->m_lock.Lock();
	IocpPacket* pIocpPacket=NULL;
	pIocpPacket= pPoolList->m_pBuffer;
	if (NULL!=pIocpPacket) 
	{		
		CmASSERT(false==pIocpPacket->IsUse());
		pIocpPacket->Clear();
		pPoolList->m_pBuffer = pIocpPacket->m_pNext;
	}
	else
	{		
		pIocpPacket = new IocpPacket;		
		PacketAlloc::AddCheckList(pIocpPacket);			
	}

	pIocpPacket->SetUse(true);

	pPoolList->m_lock.Unlock();

	return pIocpPacket;
}

IocpPacket* IoPacketPool::Alloc()
{
	IocpPacket*newBuffer = AllocBuffer();

	newBuffer->m_pNext = NULL;
	return newBuffer;
}

IocpPacket* IoPacketPool::GetRecvBuffer()
{
	IocpPacket* pIocpPacket = Alloc();
	pIocpPacket->m_pPacket = new BYTE[EACH_BUF_SIZE];
	pIocpPacket->m_size = EACH_BUF_SIZE;
	pIocpPacket->m_startPos =0;
	return pIocpPacket;
}

void IoPacketPool::ReleaseBuffer(IocpPacket* pIocpPacket)
{
	pIocpPacket->m_startPos=0;
	pIocpPacket->m_size = 0;
	pIocpPacket->DeletePacket();
	Free(pIocpPacket);
}

//////////////////////////////////////////////////////////////////////////
// IocpPacket
//////////////////////////////////////////////////////////////////////////
IocpPacket::IocpPacket()
	:m_startPos(0)
{
	m_pNext=NULL;
	Clear();
}

IocpPacket::~IocpPacket()
{
}

void IocpPacket::Clear()
{
	m_bUse=false;
	m_size = 0;//pIocpPacketPool::EACH_BUF_SIZE;
	m_pPacket=nullptr;
	//m_pPacket= new BYTE(m_size);	
	//ZeroMemory( m_pPacket, m_size);

	m_startPos=0;
}


void IocpPacket::SetPacket(unsigned long type, BYTE* pPacket, const size_t& size)
{
	if(0>=size)
		return;

	NetPacket netpacket;
	netpacket.GetHeader()->_type=type;
	netpacket.GetHeader()->_size=size;
	netpacket.GetBody()->_pBody = pPacket;

	m_size=size+NetPacket::GetHeaderSize();	
	m_pPacket = new BYTE[m_size];
	
	memcpy_s(m_pPacket, NetPacket::GetHeaderSize(), netpacket.GetHeader(), NetPacket::GetHeaderSize());	
	memcpy_s(m_pPacket+NetPacket::GetHeaderSize(), size, pPacket, size);	
}

void IocpPacket::DeletePacket()
{
	CmSAFE_DELETE(m_pPacket);
}

namespace PacketAlloc
{
	static DWORD gs_cnt=0;

	void AddCheckList(IocpPacket* pIocpPacket)
	{		
		g_lock.Lock();
		pIocpPacket->m_Index=gs_cnt++;
		mapIocpPacket::iterator it = g_mapList.find( pIocpPacket->m_Index );
		if(it==g_mapList.end())
		{
			g_mapList.insert( std::make_pair(pIocpPacket->m_Index, pIocpPacket));
		}
		else
		{		
			CmTRACE( L"[PacketAlloc] ADD: already exist %d\n", pIocpPacket->m_Index);
		}
		g_lock.Unlock();
	}

	void PopCheckList(IocpPacket* pIocpPacket)
	{		
		g_lock.Lock();
		mapIocpPacket::iterator it = g_mapList.find( pIocpPacket->m_Index );
		if(it!=g_mapList.end())
		{
			g_mapList.erase(it);				
		}
		else
		{		
			CmTRACE( L"[PacketAlloc] Pop: Don't exist %d\n", pIocpPacket->m_Index);
		}		
		g_lock.Unlock();
	}

	void CheckList()
	{
		g_lock.Lock();
		for (mapIocpPacket::iterator it = g_mapList.begin(); it!=g_mapList.end(); ++it)
		{
			CmTRACE( L"[PacketAlloc] CheckList: remained index %d\n", it->first );
		}
		g_lock.Unlock();
	}
}

/*------------------------------------------------------------------------

------------------------------------------------------------------------*/
